package cn.jaychang.demo5.auth.server.controller;

import cn.jaychang.demo5.auth.server.exception.OAuthServerWebResponseExceptionTranslator;
import cn.jaychang.demo5.common.model.LoginUser;
import cn.jaychang.demo5.common.model.Result;
import cn.jaychang.demo5.common.model.constant.SysConstant;
import cn.jaychang.demo5.common.util.OAuthUtil;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.security.oauth2.common.exceptions.BadClientCredentialsException;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.security.oauth2.provider.ClientRegistrationException;
import org.springframework.security.oauth2.provider.endpoint.CheckTokenEndpoint;
import org.springframework.security.oauth2.provider.endpoint.TokenEndpoint;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.*;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.concurrent.TimeUnit;

@Controller
@RequestMapping("/oauth")
@Slf4j
public class AuthController implements InitializingBean {
    //令牌请求的端点
    @Autowired
    private TokenEndpoint tokenEndpoint;

    @Autowired
    private CheckTokenEndpoint checkTokenEndpoint;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    //自定义异常翻译器，针对用户名、密码异常，授权类型不支持的异常进行处理
    private OAuthServerWebResponseExceptionTranslator translate;


    @PostMapping("/logout")
    @ResponseBody
    public Result logout(){
        LoginUser loginVal = OAuthUtil.getCurrentUser();
        log.info("令牌唯一ID：{},过期时间：{}",loginVal.getJti(),loginVal.getExpireIn());
        //这个jti放入redis中，并且过期时间设置为token的过期时间
        stringRedisTemplate.opsForValue().set(SysConstant.JTI_KEY_PREFIX+loginVal.getJti(),"",loginVal.getExpireIn(), TimeUnit.SECONDS);
        return new Result(200,"注销成功",null);
    }

    /**
     * 表单登录跳转页面
     * @param model
     * @return
     */
    @GetMapping("/login")
    public String loginPage(Model model){
        //返回跳转页面
        return "oauth-login";
    }

    /**
     * 处理授权异常的跳转页面
     * @param model
     * @return
     */
    @GetMapping("/error")
    public String errorPage(Model model){
        return "oauth-error";
    }

    /********************************************下面的@ExceptionHandler对/oauth/token这个接口的异常进行捕获**********************************************************************/
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    @ResponseBody
    public ResponseEntity<Result> handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) throws Exception {
        if (log.isInfoEnabled()) {
            log.info("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage());
        }
        return translate.translate(e);
    }

    @ExceptionHandler(Exception.class)
    @ResponseBody
    public ResponseEntity<Result> handleException(Exception e) throws Exception {
        if (log.isWarnEnabled()) {
            log.warn("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage());
        }
        return translate.translate(e);
    }

    @ExceptionHandler(ClientRegistrationException.class)
    @ResponseBody
    public ResponseEntity<Result> handleClientRegistrationException(Exception e) throws Exception {
        if (log.isWarnEnabled()) {
            log.warn("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage());
        }
        return translate.translate(new BadClientCredentialsException());
    }

    @ExceptionHandler(OAuth2Exception.class)
    @ResponseBody
    public ResponseEntity<Result> handleException(OAuth2Exception e) throws Exception {
        if (log.isWarnEnabled()) {
            log.warn("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage());
        }
        return translate.translate(e);
    }

    @Override
    public void afterPropertiesSet() {
        this.translate=new OAuthServerWebResponseExceptionTranslator();
    }
}
